package com.fuego.creditsystemgateway.config;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.fuego.creditsystemuser.service.IUserService;
import jakarta.annotation.Resource;
import org.example.dto.UserDTO;
import org.example.entity.User;
import org.example.utils.RedisConstants;
import org.example.utils.UserHolder;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class RefreshTokenGlobalFilter implements GlobalFilter, Ordered {
    private final StringRedisTemplate stringRedisTemplate;

    public RefreshTokenGlobalFilter(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Resource
    private IUserService userService;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. 获取请求头中的 token
        ServerHttpRequest request = exchange.getRequest();
        String token = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        if (StrUtil.isBlank(token)) {
            // 无 token，直接放行
            return chain.filter(exchange);
        }

        // 2. 基于 token 获取 Redis 中的用户
        String key = RedisConstants.LOGIN_USER_KEY + token;
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);

        // 3. 判断用户是否存在
        if (userMap.isEmpty()) {
            // 用户不存在，放行（或可返回 401，未授权）
            return chain.filter(exchange);
        }

        // 4. 将查询到的 Hash 数据转为 UserDTO
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
        User user=userService.getById(userDTO.getId());
        // 5. 保存用户信息到 ThreadLocal（注意：ThreadLocal 在 reactive 环境中需谨慎使用）
        UserHolder.saveUser(userDTO);

        // 6. 刷新 token 有效期
        stringRedisTemplate.expire(key, RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);

        // 7. 将用户信息添加到请求头，传递给下游服务
        ServerHttpRequest modifiedRequest = request.mutate()
                .header("X-User-Id", userDTO.getId().toString())
                .header("X-Username", user.getNickName())
                .build();
        ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();

        // 8. 放行
        return chain.filter(modifiedExchange).then(Mono.fromRunnable(UserHolder::removeUser));
    }

    @Override
    public int getOrder() {
        return -100; // 优先级较高，确保认证在其他过滤器之前
    }
}
